

 /*
 This file '_tabs' is part of Firebird Integrated Solution 1.0

 Copyright (c) 2015 Lincong

 Contact:  
        Email: lincong1987@gmail.com

        QQ: 159257119
 
 See Usage at http://www.jplatformx.com/firebird

 Create date: 2015-07-14 04:47
 */

 (function ($, undefined) {

     var tabId = 0,
         rhash = /#.*$/;

     function getNextTabId() {
         return ++tabId;
     }

     function isLocal(anchor) {
         return anchor.hash.length > 1 &&
             anchor.href.replace(rhash, "") ===
             location.href.replace(rhash, "")
                 // support: Safari 5.1
                 // Safari 5.1 doesn't encode spaces in window.location
                 // but it does encode spaces from anchors (#8777)
                 .replace(/\s/g, "%20");
     }

     $.widget("ui.tabs", {
         version: "1.9.2",
         delay: 300,
         options: {
             active: null,
             collapsible: false,
             event: "click",
             heightStyle: "content",
             hide: null,
             show: null,

             // callbacks
             activate: null,
             beforeActivate: null,
             beforeLoad: null,
             load: null
         },

         _create: function () {
             var that = this,
                 options = this.options,
                 active = options.active,
                 locationHash = location.hash.substring(1);

             this.running = false;

             this.element
                 .addClass("ui-tabs ui-widget ui-widget-content ui-corner-all")
                 .toggleClass("ui-tabs-collapsible", options.collapsible)
                 // Prevent users from focusing disabled tabs via click
                 .delegate(".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function (event) {
                     if ($(this).is(".ui-state-disabled")) {
                         event.preventDefault();
                     }
                 })
                 // support: IE <9
                 // Preventing the default action in mousedown doesn't prevent IE
                 // from focusing the element, so if the anchor gets focused, blur.
                 // We don't have to worry about focusing the previously focused
                 // element since clicking on a non-focusable element should focus
                 // the body anyway.
                 .delegate(".ui-tabs-anchor", "focus" + this.eventNamespace, function () {
                     if ($(this).closest("li").is(".ui-state-disabled")) {
                         this.blur();
                     }
                 });

             this._processTabs();

             if (active === null) {
                 // check the fragment identifier in the URL
                 if (locationHash) {
                     this.tabs.each(function (i, tab) {
                         if ($(tab).attr("aria-controls") === locationHash) {
                             active = i;
                             return false;
                         }
                     });
                 }

                 // check for a tab marked active via a class
                 if (active === null) {
                     active = this.tabs.index(this.tabs.filter(".ui-tabs-active"));
                 }

                 // no active tab, set to false
                 if (active === null || active === -1) {
                     active = this.tabs.length ? 0 : false;
                 }
             }

             // handle numbers: negative, out of range
             if (active !== false) {
                 active = this.tabs.index(this.tabs.eq(active));
                 if (active === -1) {
                     active = options.collapsible ? false : 0;
                 }
             }
             options.active = active;

             // don't allow collapsible: false and active: false
             if (!options.collapsible && options.active === false && this.anchors.length) {
                 options.active = 0;
             }

             // Take disabling tabs via class attribute from HTML
             // into account and update option properly.
             if ($.isArray(options.disabled)) {
                 options.disabled = $.unique(options.disabled.concat(
                     $.map(this.tabs.filter(".ui-state-disabled"), function (li) {
                         return that.tabs.index(li);
                     })
                 )).sort();
             }

             // check for length avoids error when initializing empty list
             if (this.options.active !== false && this.anchors.length) {
                 this.active = this._findActive(this.options.active);
             } else {
                 this.active = $();
             }

             this._refresh();

             if (this.active.length) {
                 this.load(options.active);
             }
         },

         _getCreateEventData: function () {
             return {
                 tab: this.active,
                 panel: !this.active.length ? $() : this._getPanelForTab(this.active)
             };
         },

         _tabKeydown: function (event) {
             var focusedTab = $(this.document[0].activeElement).closest("li"),
                 selectedIndex = this.tabs.index(focusedTab),
                 goingForward = true;

             if (this._handlePageNav(event)) {
                 return;
             }

             switch (event.keyCode) {
                 case $.ui.keyCode.RIGHT:
                 case $.ui.keyCode.DOWN:
                     selectedIndex++;
                     break;
                 case $.ui.keyCode.UP:
                 case $.ui.keyCode.LEFT:
                     goingForward = false;
                     selectedIndex--;
                     break;
                 case $.ui.keyCode.END:
                     selectedIndex = this.anchors.length - 1;
                     break;
                 case $.ui.keyCode.HOME:
                     selectedIndex = 0;
                     break;
                 case $.ui.keyCode.SPACE:
                     // Activate only, no collapsing
                     event.preventDefault();
                     clearTimeout(this.activating);
                     this._activate(selectedIndex);
                     return;
                 case $.ui.keyCode.ENTER:
                     // Toggle (cancel delayed activation, allow collapsing)
                     event.preventDefault();
                     clearTimeout(this.activating);
                     // Determine if we should collapse or activate
                     this._activate(selectedIndex === this.options.active ? false : selectedIndex);
                     return;
                 default:
                     return;
             }

             // Focus the appropriate tab, based on which key was pressed
             event.preventDefault();
             clearTimeout(this.activating);
             selectedIndex = this._focusNextTab(selectedIndex, goingForward);

             // Navigating with control key will prevent automatic activation
             if (!event.ctrlKey) {
                 // Update aria-selected immediately so that AT think the tab is already selected.
                 // Otherwise AT may confuse the user by stating that they need to activate the tab,
                 // but the tab will already be activated by the time the announcement finishes.
                 focusedTab.attr("aria-selected", "false");
                 this.tabs.eq(selectedIndex).attr("aria-selected", "true");

                 this.activating = this._delay(function () {
                     this.option("active", selectedIndex);
                 }, this.delay);
             }
         },

         _panelKeydown: function (event) {
             if (this._handlePageNav(event)) {
                 return;
             }

             // Ctrl+up moves focus to the current tab
             if (event.ctrlKey && event.keyCode === $.ui.keyCode.UP) {
                 event.preventDefault();
                 this.active.focus();
             }
         },

         // Alt+page up/down moves focus to the previous/next tab (and activates)
         _handlePageNav: function (event) {
             if (event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP) {
                 this._activate(this._focusNextTab(this.options.active - 1, false));
                 return true;
             }
             if (event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN) {
                 this._activate(this._focusNextTab(this.options.active + 1, true));
                 return true;
             }
         },

         _findNextTab: function (index, goingForward) {
             var lastTabIndex = this.tabs.length - 1;

             function constrain() {
                 if (index > lastTabIndex) {
                     index = 0;
                 }
                 if (index < 0) {
                     index = lastTabIndex;
                 }
                 return index;
             }

             while ($.inArray(constrain(), this.options.disabled) !== -1) {
                 index = goingForward ? index + 1 : index - 1;
             }

             return index;
         },

         _focusNextTab: function (index, goingForward) {
             index = this._findNextTab(index, goingForward);
             this.tabs.eq(index).focus();
             return index;
         },

         _setOption: function (key, value) {
             if (key === "active") {
                 // _activate() will handle invalid values and update this.options
                 this._activate(value);
                 return;
             }

             if (key === "disabled") {
                 // don't use the widget factory's disabled handling
                 this._setupDisabled(value);
                 return;
             }

             this._super(key, value);

             if (key === "collapsible") {
                 this.element.toggleClass("ui-tabs-collapsible", value);
                 // Setting collapsible: false while collapsed; open first panel
                 if (!value && this.options.active === false) {
                     this._activate(0);
                 }
             }

             if (key === "event") {
                 this._setupEvents(value);
             }

             if (key === "heightStyle") {
                 this._setupHeightStyle(value);
             }
         },

         _tabId: function (tab) {
             return tab.attr("aria-controls") || "ui-tabs-" + getNextTabId();
         },

         _sanitizeSelector: function (hash) {
             return hash ? hash.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&") : "";
         },

         refresh: function () {
             var options = this.options,
                 lis = this.tablist.children(":has(a[href])");

             // get disabled tabs from class attribute from HTML
             // this will get converted to a boolean if needed in _refresh()
             options.disabled = $.map(lis.filter(".ui-state-disabled"), function (tab) {
                 return lis.index(tab);
             });

             this._processTabs();

             // was collapsed or no tabs
             if (options.active === false || !this.anchors.length) {
                 options.active = false;
                 this.active = $();
                 // was active, but active tab is gone
             } else if (this.active.length && !$.contains(this.tablist[0], this.active[0])) {
                 // all remaining tabs are disabled
                 if (this.tabs.length === options.disabled.length) {
                     options.active = false;
                     this.active = $();
                     // activate previous tab
                 } else {
                     this._activate(this._findNextTab(Math.max(0, options.active - 1), false));
                 }
                 // was active, active tab still exists
             } else {
                 // make sure active index is correct
                 options.active = this.tabs.index(this.active);
             }

             this._refresh();
         },

         _refresh: function () {
             this._setupDisabled(this.options.disabled);
             this._setupEvents(this.options.event);
             this._setupHeightStyle(this.options.heightStyle);

             this.tabs.not(this.active).attr({
                 "aria-selected": "false",
                 tabIndex: -1
             });
             this.panels.not(this._getPanelForTab(this.active))
                 .hide()
                 .attr({
                     "aria-expanded": "false",
                     "aria-hidden": "true"
                 });

             // Make sure one tab is in the tab order
             if (!this.active.length) {
                 this.tabs.eq(0).attr("tabIndex", 0);
             } else {
                 this.active
                     .addClass("ui-tabs-active ui-state-active")
                     .attr({
                         "aria-selected": "true",
                         tabIndex: 0
                     });
                 this._getPanelForTab(this.active)
                     .show()
                     .attr({
                         "aria-expanded": "true",
                         "aria-hidden": "false"
                     });
             }
         },

         _processTabs: function () {
             var that = this;

             this.tablist = this._getList()
                 .addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all")
                 .attr("role", "tablist");

             this.tabs = this.tablist.find("> li:has(a[href])")
                 .addClass("ui-state-default ui-corner-top")
                 .attr({
                     role: "tab",
                     tabIndex: -1
                 });

             this.anchors = this.tabs.map(function () {
                 return $("a", this)[0];
             })
                 .addClass("ui-tabs-anchor")
                 .attr({
                     role: "presentation",
                     tabIndex: -1
                 });

             this.panels = $();

             this.anchors.each(function (i, anchor) {
                 var selector, panel, panelId,
                     anchorId = $(anchor).uniqueId().attr("id"),
                     tab = $(anchor).closest("li"),
                     originalAriaControls = tab.attr("aria-controls");

                 // inline tab
                 if (isLocal(anchor)) {
                     selector = anchor.hash;
                     panel = that.element.find(that._sanitizeSelector(selector));
                     // remote tab
                 } else {
                     panelId = that._tabId(tab);
                     selector = "#" + panelId;
                     panel = that.element.find(selector);
                     if (!panel.length) {
                         panel = that._createPanel(panelId);
                         panel.insertAfter(that.panels[i - 1] || that.tablist);
                     }
                     panel.attr("aria-live", "polite");
                 }

                 if (panel.length) {
                     that.panels = that.panels.add(panel);
                 }
                 if (originalAriaControls) {
                     tab.data("ui-tabs-aria-controls", originalAriaControls);
                 }
                 tab.attr({
                     "aria-controls": selector.substring(1),
                     "aria-labelledby": anchorId
                 });
                 panel.attr("aria-labelledby", anchorId);
             });

             this.panels
                 .addClass("ui-tabs-panel ui-widget-content ui-corner-bottom")
                 .attr("role", "tabpanel");
         },

         // allow overriding how to find the list for rare usage scenarios (#7715)
         _getList: function () {
             return this.element.find("ol,ul").eq(0);
         },

         _createPanel: function (id) {
             return $("<div>")
                 .attr("id", id)
                 .addClass("ui-tabs-panel ui-widget-content ui-corner-bottom")
                 .data("ui-tabs-destroy", true);
         },

         _setupDisabled: function (disabled) {
             if ($.isArray(disabled)) {
                 if (!disabled.length) {
                     disabled = false;
                 } else if (disabled.length === this.anchors.length) {
                     disabled = true;
                 }
             }

             // disable tabs
             for (var i = 0, li; ( li = this.tabs[i] ); i++) {
                 if (disabled === true || $.inArray(i, disabled) !== -1) {
                     $(li)
                         .addClass("ui-state-disabled")
                         .attr("aria-disabled", "true");
                 } else {
                     $(li)
                         .removeClass("ui-state-disabled")
                         .removeAttr("aria-disabled");
                 }
             }

             this.options.disabled = disabled;
         },

         _setupEvents: function (event) {
             var events = {
                 click: function (event) {
                     event.preventDefault();
                 }
             };
             if (event) {
                 $.each(event.split(" "), function (index, eventName) {
                     events[eventName] = "_eventHandler";
                 });
             }

             this._off(this.anchors.add(this.tabs).add(this.panels));
             this._on(this.anchors, events);
             this._on(this.tabs, {keydown: "_tabKeydown"});
             this._on(this.panels, {keydown: "_panelKeydown"});

             this._focusable(this.tabs);
             this._hoverable(this.tabs);
         },

         _setupHeightStyle: function (heightStyle) {
             var maxHeight, overflow,
                 parent = this.element.parent();

             if (heightStyle === "fill") {
                 // IE 6 treats height like minHeight, so we need to turn off overflow
                 // in order to get a reliable height
                 // we use the minHeight support test because we assume that only
                 // browsers that don't support minHeight will treat height as minHeight
                 if (!$.support.minHeight) {
                     overflow = parent.css("overflow");
                     parent.css("overflow", "hidden");
                 }
                 maxHeight = parent.height();
                 this.element.siblings(":visible").each(function () {
                     var elem = $(this),
                         position = elem.css("position");

                     if (position === "absolute" || position === "fixed") {
                         return;
                     }
                     maxHeight -= elem.outerHeight(true);
                 });
                 if (overflow) {
                     parent.css("overflow", overflow);
                 }

                 this.element.children().not(this.panels).each(function () {
                     maxHeight -= $(this).outerHeight(true);
                 });

                 this.panels.each(function () {
                     $(this).height(Math.max(0, maxHeight -
                         $(this).innerHeight() + $(this).height()));
                 })
                     .css("overflow", "auto");
             } else if (heightStyle === "auto") {
                 maxHeight = 0;
                 this.panels.each(function () {
                     maxHeight = Math.max(maxHeight, $(this).height("").height());
                 }).height(maxHeight);
             }
         },

         _eventHandler: function (event) {
             var options = this.options,
                 active = this.active,
                 anchor = $(event.currentTarget),
                 tab = anchor.closest("li"),
                 clickedIsActive = tab[0] === active[0],
                 collapsing = clickedIsActive && options.collapsible,
                 toShow = collapsing ? $() : this._getPanelForTab(tab),
                 toHide = !active.length ? $() : this._getPanelForTab(active),
                 eventData = {
                     oldTab: active,
                     oldPanel: toHide,
                     newTab: collapsing ? $() : tab,
                     newPanel: toShow
                 };

             event.preventDefault();

             if (tab.hasClass("ui-state-disabled") ||
                     // tab is already loading
                 tab.hasClass("ui-tabs-loading") ||
                     // can't switch durning an animation
                 this.running ||
                     // click on active header, but not collapsible
                 ( clickedIsActive && !options.collapsible ) ||
                     // allow canceling activation
                 ( this._trigger("beforeActivate", event, eventData) === false )) {
                 return;
             }

             options.active = collapsing ? false : this.tabs.index(tab);

             this.active = clickedIsActive ? $() : tab;
             if (this.xhr) {
                 this.xhr.abort();
             }

             if (!toHide.length && !toShow.length) {
                 $.error("jQuery UI Tabs: Mismatching fragment identifier.");
             }

             if (toShow.length) {
                 this.load(this.tabs.index(tab), event);
             }
             this._toggle(event, eventData);
         },

         // handles show/hide for selecting tabs
         _toggle: function (event, eventData) {
             var that = this,
                 toShow = eventData.newPanel,
                 toHide = eventData.oldPanel;

             this.running = true;

             function complete() {
                 that.running = false;
                 that._trigger("activate", event, eventData);
             }

             function show() {
                 eventData.newTab.closest("li").addClass("ui-tabs-active ui-state-active");

                 if (toShow.length && that.options.show) {
                     that._show(toShow, that.options.show, complete);
                 } else {
                     toShow.show();
                     complete();
                 }
             }

             // start out by hiding, then showing, then completing
             if (toHide.length && this.options.hide) {
                 this._hide(toHide, this.options.hide, function () {
                     eventData.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active");
                     show();
                 });
             } else {
                 eventData.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active");
                 toHide.hide();
                 show();
             }

             toHide.attr({
                 "aria-expanded": "false",
                 "aria-hidden": "true"
             });
             eventData.oldTab.attr("aria-selected", "false");
             // If we're switching tabs, remove the old tab from the tab order.
             // If we're opening from collapsed state, remove the previous tab from the tab order.
             // If we're collapsing, then keep the collapsing tab in the tab order.
             if (toShow.length && toHide.length) {
                 eventData.oldTab.attr("tabIndex", -1);
             } else if (toShow.length) {
                 this.tabs.filter(function () {
                     return $(this).attr("tabIndex") === 0;
                 })
                     .attr("tabIndex", -1);
             }

             toShow.attr({
                 "aria-expanded": "true",
                 "aria-hidden": "false"
             });
             eventData.newTab.attr({
                 "aria-selected": "true",
                 tabIndex: 0
             });
         },

         _activate: function (index) {
             var anchor,
                 active = this._findActive(index);

             // trying to activate the already active panel
             if (active[0] === this.active[0]) {
                 return;
             }

             // trying to collapse, simulate a click on the current active header
             if (!active.length) {
                 active = this.active;
             }

             anchor = active.find(".ui-tabs-anchor")[0];
             this._eventHandler({
                 target: anchor,
                 currentTarget: anchor,
                 preventDefault: $.noop
             });
         },

         _findActive: function (index) {
             return index === false ? $() : this.tabs.eq(index);
         },

         _getIndex: function (index) {
             // meta-function to give users option to provide a href string instead of a numerical index.
             if (typeof index === "string") {
                 index = this.anchors.index(this.anchors.filter("[href$='" + index + "']"));
             }

             return index;
         },

         _destroy: function () {
             if (this.xhr) {
                 this.xhr.abort();
             }

             this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible");

             this.tablist
                 .removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all")
                 .removeAttr("role");

             this.anchors
                 .removeClass("ui-tabs-anchor")
                 .removeAttr("role")
                 .removeAttr("tabIndex")
                 .removeData("href.tabs")
                 .removeData("load.tabs")
                 .removeUniqueId();

             this.tabs.add(this.panels).each(function () {
                 if ($.data(this, "ui-tabs-destroy")) {
                     $(this).remove();
                 } else {
                     $(this)
                         .removeClass("ui-state-default ui-state-active ui-state-disabled " +
                         "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel")
                         .removeAttr("tabIndex")
                         .removeAttr("aria-live")
                         .removeAttr("aria-busy")
                         .removeAttr("aria-selected")
                         .removeAttr("aria-labelledby")
                         .removeAttr("aria-hidden")
                         .removeAttr("aria-expanded")
                         .removeAttr("role");
                 }
             });

             this.tabs.each(function () {
                 var li = $(this),
                     prev = li.data("ui-tabs-aria-controls");
                 if (prev) {
                     li.attr("aria-controls", prev);
                 } else {
                     li.removeAttr("aria-controls");
                 }
             });

             this.panels.show();

             if (this.options.heightStyle !== "content") {
                 this.panels.css("height", "");
             }
         },

         enable: function (index) {
             var disabled = this.options.disabled;
             if (disabled === false) {
                 return;
             }

             if (index === undefined) {
                 disabled = false;
             } else {
                 index = this._getIndex(index);
                 if ($.isArray(disabled)) {
                     disabled = $.map(disabled, function (num) {
                         return num !== index ? num : null;
                     });
                 } else {
                     disabled = $.map(this.tabs, function (li, num) {
                         return num !== index ? num : null;
                     });
                 }
             }
             this._setupDisabled(disabled);
         },

         disable: function (index) {
             var disabled = this.options.disabled;
             if (disabled === true) {
                 return;
             }

             if (index === undefined) {
                 disabled = true;
             } else {
                 index = this._getIndex(index);
                 if ($.inArray(index, disabled) !== -1) {
                     return;
                 }
                 if ($.isArray(disabled)) {
                     disabled = $.merge([index], disabled).sort();
                 } else {
                     disabled = [index];
                 }
             }
             this._setupDisabled(disabled);
         },

         load: function (index, event) {
             index = this._getIndex(index);
             var that = this,
                 tab = this.tabs.eq(index),
                 anchor = tab.find(".ui-tabs-anchor"),
                 panel = this._getPanelForTab(tab),
                 eventData = {
                     tab: tab,
                     panel: panel
                 };

             // not remote
             if (isLocal(anchor[0])) {
                 return;
             }

             this.xhr = $.ajax(this._ajaxSettings(anchor, event, eventData));

             // support: jQuery <1.8
             // jQuery <1.8 returns false if the request is canceled in beforeSend,
             // but as of 1.8, $.ajax() always returns a jqXHR object.
             if (this.xhr && this.xhr.statusText !== "canceled") {
                 tab.addClass("ui-tabs-loading");
                 panel.attr("aria-busy", "true");

                 this.xhr
                     .success(function (response) {
                         // support: jQuery <1.8
                         // http://bugs.jquery.com/ticket/11778
                         setTimeout(function () {
                             panel.html(response);
                             that._trigger("load", event, eventData);
                         }, 1);
                     })
                     .complete(function (jqXHR, status) {
                         // support: jQuery <1.8
                         // http://bugs.jquery.com/ticket/11778
                         setTimeout(function () {
                             if (status === "abort") {
                                 that.panels.stop(false, true);
                             }

                             tab.removeClass("ui-tabs-loading");
                             panel.removeAttr("aria-busy");

                             if (jqXHR === that.xhr) {
                                 delete that.xhr;
                             }
                         }, 1);
                     });
             }
         },

         // TODO: Remove this function in 1.10 when ajaxOptions is removed
         _ajaxSettings: function (anchor, event, eventData) {
             var that = this;
             return {
                 url: anchor.attr("href"),
                 beforeSend: function (jqXHR, settings) {
                     return that._trigger("beforeLoad", event,
                         $.extend({jqXHR: jqXHR, ajaxSettings: settings}, eventData));
                 }
             };
         },

         _getPanelForTab: function (tab) {
             var id = $(tab).attr("aria-controls");
             return this.element.find(this._sanitizeSelector("#" + id));
         }
     });

// DEPRECATED
     if ($.uiBackCompat !== false) {

         // helper method for a lot of the back compat extensions
         $.ui.tabs.prototype._ui = function (tab, panel) {
             return {
                 tab: tab,
                 panel: panel,
                 index: this.anchors.index(tab)
             };
         };

         // url method
         $.widget("ui.tabs", $.ui.tabs, {
             url: function (index, url) {
                 this.anchors.eq(index).attr("href", url);
             }
         });

         // TODO: Remove _ajaxSettings() method when removing this extension
         // ajaxOptions and cache options
         $.widget("ui.tabs", $.ui.tabs, {
             options: {
                 ajaxOptions: null,
                 cache: false
             },

             _create: function () {
                 this._super();

                 var that = this;

                 this._on({
                     tabsbeforeload: function (event, ui) {
                         // tab is already cached
                         if ($.data(ui.tab[0], "cache.tabs")) {
                             event.preventDefault();
                             return;
                         }

                         ui.jqXHR.success(function () {
                             if (that.options.cache) {
                                 $.data(ui.tab[0], "cache.tabs", true);
                             }
                         });
                     }
                 });
             },

             _ajaxSettings: function (anchor, event, ui) {
                 var ajaxOptions = this.options.ajaxOptions;
                 return $.extend({}, ajaxOptions, {
                     error: function (xhr, status) {
                         try {
                             // Passing index avoid a race condition when this method is
                             // called after the user has selected another tab.
                             // Pass the anchor that initiated this request allows
                             // loadError to manipulate the tab content panel via $(a.hash)
                             ajaxOptions.error(
                                 xhr, status, ui.tab.closest("li").index(), ui.tab[0]);
                         }
                         catch (error) {
                         }
                     }
                 }, this._superApply(arguments));
             },

             _setOption: function (key, value) {
                 // reset cache if switching from cached to not cached
                 if (key === "cache" && value === false) {
                     this.anchors.removeData("cache.tabs");
                 }
                 this._super(key, value);
             },

             _destroy: function () {
                 this.anchors.removeData("cache.tabs");
                 this._super();
             },

             url: function (index) {
                 this.anchors.eq(index).removeData("cache.tabs");
                 this._superApply(arguments);
             }
         });

         // abort method
         $.widget("ui.tabs", $.ui.tabs, {
             abort: function () {
                 if (this.xhr) {
                     this.xhr.abort();
                 }
             }
         });

         // spinner
         $.widget("ui.tabs", $.ui.tabs, {
             options: {
                 spinner: "<em>Loading&#8230;</em>"
             },
             _create: function () {
                 this._super();
                 this._on({
                     tabsbeforeload: function (event, ui) {
                         // Don't react to nested tabs or tabs that don't use a spinner
                         if (event.target !== this.element[0] || !this.options.spinner) {
                             return;
                         }

                         var span = ui.tab.find("span"),
                             html = span.html();
                         span.html(this.options.spinner);
                         ui.jqXHR.complete(function () {
                             span.html(html);
                         });
                     }
                 });
             }
         });

         // enable/disable events
         $.widget("ui.tabs", $.ui.tabs, {
             options: {
                 enable: null,
                 disable: null
             },

             enable: function (index) {
                 var options = this.options,
                     trigger;

                 if (index && options.disabled === true ||
                     ( $.isArray(options.disabled) && $.inArray(index, options.disabled) !== -1 )) {
                     trigger = true;
                 }

                 this._superApply(arguments);

                 if (trigger) {
                     this._trigger("enable", null, this._ui(this.anchors[index], this.panels[index]));
                 }
             },

             disable: function (index) {
                 var options = this.options,
                     trigger;

                 if (index && options.disabled === false ||
                     ( $.isArray(options.disabled) && $.inArray(index, options.disabled) === -1 )) {
                     trigger = true;
                 }

                 this._superApply(arguments);

                 if (trigger) {
                     this._trigger("disable", null, this._ui(this.anchors[index], this.panels[index]));
                 }
             }
         });

         // add/remove methods and events
         $.widget("ui.tabs", $.ui.tabs, {
             options: {
                 add: null,
                 remove: null,
                 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
             },

             add: function (url, label, index) {
                 if (index === undefined) {
                     index = this.anchors.length;
                 }

                 var doInsertAfter, panel,
                     options = this.options,
                     li = $(options.tabTemplate
                         .replace(/#\{href\}/g, url)
                         .replace(/#\{label\}/g, label)),
                     id = !url.indexOf("#") ?
                         url.replace("#", "") :
                         this._tabId(li);

                 li.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy", true);
                 li.attr("aria-controls", id);

                 doInsertAfter = index >= this.tabs.length;

                 // try to find an existing element before creating a new one
                 panel = this.element.find("#" + id);
                 if (!panel.length) {
                     panel = this._createPanel(id);
                     if (doInsertAfter) {
                         if (index > 0) {
                             panel.insertAfter(this.panels.eq(-1));
                         } else {
                             panel.appendTo(this.element);
                         }
                     } else {
                         panel.insertBefore(this.panels[index]);
                     }
                 }
                 panel.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide();

                 if (doInsertAfter) {
                     li.appendTo(this.tablist);
                 } else {
                     li.insertBefore(this.tabs[index]);
                 }

                 options.disabled = $.map(options.disabled, function (n) {
                     return n >= index ? ++n : n;
                 });

                 this.refresh();
                 if (this.tabs.length === 1 && options.active === false) {
                     this.option("active", 0);
                 }

                 this._trigger("add", null, this._ui(this.anchors[index], this.panels[index]));
                 return this;
             },

             remove: function (index) {
                 index = this._getIndex(index);
                 var options = this.options,
                     tab = this.tabs.eq(index).remove(),
                     panel = this._getPanelForTab(tab).remove();

                 // If selected tab was removed focus tab to the right or
                 // in case the last tab was removed the tab to the left.
                 // We check for more than 2 tabs, because if there are only 2,
                 // then when we remove this tab, there will only be one tab left
                 // so we don't need to detect which tab to activate.
                 if (tab.hasClass("ui-tabs-active") && this.anchors.length > 2) {
                     this._activate(index + ( index + 1 < this.anchors.length ? 1 : -1 ));
                 }

                 options.disabled = $.map(
                     $.grep(options.disabled, function (n) {
                         return n !== index;
                     }),
                     function (n) {
                         return n >= index ? --n : n;
                     });

                 this.refresh();

                 this._trigger("remove", null, this._ui(tab.find("a")[0], panel[0]));
                 return this;
             }
         });

         // length method
         $.widget("ui.tabs", $.ui.tabs, {
             length: function () {
                 return this.anchors.length;
             }
         });

         // panel ids (idPrefix option + title attribute)
         $.widget("ui.tabs", $.ui.tabs, {
             options: {
                 idPrefix: "ui-tabs-"
             },

             _tabId: function (tab) {
                 var a = tab.is("li") ? tab.find("a[href]") : tab;
                 a = a[0];
                 return $(a).closest("li").attr("aria-controls") ||
                     a.title && a.title.replace(/\s/g, "_").replace(/[^\w\u00c0-\uFFFF\-]/g, "") ||
                     this.options.idPrefix + getNextTabId();
             }
         });

         // _createPanel method
         $.widget("ui.tabs", $.ui.tabs, {
             options: {
                 panelTemplate: "<div></div>"
             },

             _createPanel: function (id) {
                 return $(this.options.panelTemplate)
                     .attr("id", id)
                     .addClass("ui-tabs-panel ui-widget-content ui-corner-bottom")
                     .data("ui-tabs-destroy", true);
             }
         });

         // selected option
         $.widget("ui.tabs", $.ui.tabs, {
             _create: function () {
                 var options = this.options;
                 if (options.active === null && options.selected !== undefined) {
                     options.active = options.selected === -1 ? false : options.selected;
                 }
                 this._super();
                 options.selected = options.active;
                 if (options.selected === false) {
                     options.selected = -1;
                 }
             },

             _setOption: function (key, value) {
                 if (key !== "selected") {
                     return this._super(key, value);
                 }

                 var options = this.options;
                 this._super("active", value === -1 ? false : value);
                 options.selected = options.active;
                 if (options.selected === false) {
                     options.selected = -1;
                 }
             },

             _eventHandler: function () {
                 this._superApply(arguments);
                 this.options.selected = this.options.active;
                 if (this.options.selected === false) {
                     this.options.selected = -1;
                 }
             }
         });

         // show and select event
         $.widget("ui.tabs", $.ui.tabs, {
             options: {
                 show: null,
                 select: null
             },
             _create: function () {
                 this._super();
                 if (this.options.active !== false) {
                     this._trigger("show", null, this._ui(
                         this.active.find(".ui-tabs-anchor")[0],
                         this._getPanelForTab(this.active)[0]));
                 }
             },
             _trigger: function (type, event, data) {
                 var tab, panel,
                     ret = this._superApply(arguments);

                 if (!ret) {
                     return false;
                 }

                 if (type === "beforeActivate") {
                     tab = data.newTab.length ? data.newTab : data.oldTab;
                     panel = data.newPanel.length ? data.newPanel : data.oldPanel;
                     ret = this._super("select", event, {
                         tab: tab.find(".ui-tabs-anchor")[0],
                         panel: panel[0],
                         index: tab.closest("li").index()
                     });
                 } else if (type === "activate" && data.newTab.length) {
                     ret = this._super("show", event, {
                         tab: data.newTab.find(".ui-tabs-anchor")[0],
                         panel: data.newPanel[0],
                         index: data.newTab.closest("li").index()
                     });
                 }
                 return ret;
             }
         });

         // select method
         $.widget("ui.tabs", $.ui.tabs, {
             select: function (index) {
                 index = this._getIndex(index);
                 if (index === -1) {
                     if (this.options.collapsible && this.options.selected !== -1) {
                         index = this.options.selected;
                     } else {
                         return;
                     }
                 }
                 this.anchors.eq(index).trigger(this.options.event + this.eventNamespace);
             }
         });

         // cookie option
         (function () {

             var listId = 0;

             $.widget("ui.tabs", $.ui.tabs, {
                 options: {
                     cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
                 },
                 _create: function () {
                     var options = this.options,
                         active;
                     if (options.active == null && options.cookie) {
                         active = parseInt(this._cookie(), 10);
                         if (active === -1) {
                             active = false;
                         }
                         options.active = active;
                     }
                     this._super();
                 },
                 _cookie: function (active) {
                     var cookie = [this.cookie ||
                     ( this.cookie = this.options.cookie.name || "ui-tabs-" + (++listId) )];
                     if (arguments.length) {
                         cookie.push(active === false ? -1 : active);
                         cookie.push(this.options.cookie);
                     }
                     return $.cookie.apply(null, cookie);
                 },
                 _refresh: function () {
                     this._super();
                     if (this.options.cookie) {
                         this._cookie(this.options.active, this.options.cookie);
                     }
                 },
                 _eventHandler: function () {
                     this._superApply(arguments);
                     if (this.options.cookie) {
                         this._cookie(this.options.active, this.options.cookie);
                     }
                 },
                 _destroy: function () {
                     this._super();
                     if (this.options.cookie) {
                         this._cookie(null, this.options.cookie);
                     }
                 }
             });

         })();

         // load event
         $.widget("ui.tabs", $.ui.tabs, {
             _trigger: function (type, event, data) {
                 var _data = $.extend({}, data);
                 if (type === "load") {
                     _data.panel = _data.panel[0];
                     _data.tab = _data.tab.find(".ui-tabs-anchor")[0];
                 }
                 return this._super(type, event, _data);
             }
         });

         // fx option
         // The new animation options (show, hide) conflict with the old show callback.
         // The old fx option wins over show/hide anyway (always favor back-compat).
         // If a user wants to use the new animation API, they must give up the old API.
         $.widget("ui.tabs", $.ui.tabs, {
             options: {
                 fx: null // e.g. { height: "toggle", opacity: "toggle", duration: 200 }
             },

             _getFx: function () {
                 var hide, show,
                     fx = this.options.fx;

                 if (fx) {
                     if ($.isArray(fx)) {
                         hide = fx[0];
                         show = fx[1];
                     } else {
                         hide = show = fx;
                     }
                 }

                 return fx ? {show: show, hide: hide} : null;
             },

             _toggle: function (event, eventData) {
                 var that = this,
                     toShow = eventData.newPanel,
                     toHide = eventData.oldPanel,
                     fx = this._getFx();

                 if (!fx) {
                     return this._super(event, eventData);
                 }

                 that.running = true;

                 function complete() {
                     that.running = false;
                     that._trigger("activate", event, eventData);
                 }

                 function show() {
                     eventData.newTab.closest("li").addClass("ui-tabs-active ui-state-active");

                     if (toShow.length && fx.show) {
                         toShow
                             .animate(fx.show, fx.show.duration, function () {
                                 complete();
                             });
                     } else {
                         toShow.show();
                         complete();
                     }
                 }

                 // start out by hiding, then showing, then completing
                 if (toHide.length && fx.hide) {
                     toHide.animate(fx.hide, fx.hide.duration, function () {
                         eventData.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active");
                         show();
                     });
                 } else {
                     eventData.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active");
                     toHide.hide();
                     show();
                 }
             }
         });
     }

 })(jQuery);